package com.zyao89.view.zloading.circle;

import com.zyao89.view.zloading.ZLoadingBuilder;
import com.zyao89.view.zloading.util.NumCalcUtil;
import ohos.agp.animation.Animator;
import ohos.agp.animation.AnimatorValue;
import ohos.agp.render.Arc;
import ohos.agp.render.Canvas;
import ohos.agp.render.ColorFilter;
import ohos.agp.render.Paint;
import ohos.agp.render.Path;
import ohos.agp.render.PathMeasure;
import ohos.agp.utils.Color;
import ohos.agp.utils.RectFloat;
import ohos.app.Context;

/**
 * Created by zyao89 on 2017/10/9.
 * Contact me at 305161066@qq.com or zyao89@gmail.com
 * For more projects: https://github.com/zyao89
 * My Blog: https://zyao89.cn
 */
public class SnakeCircleBuilder extends ZLoadingBuilder {

    // 最终阶段
    private static final int FINAL_STATE = 1;

    // 当前动画阶段
    private int mCurrAnimatorState = 0;
    private Paint mStrokePaint;
    private float mOuterRF;
    private float mInterRF;
    private RectFloat mOuterCircleRectF;
    private RectFloat mInterCircleRectF;
    private int mAlpha = 1;

    // 旋转角度
    private float mRotateAngle;
    private float mAntiRotateAngle;

    // 路径
    private Path mPath;
    private PathMeasure mPathMeasure;
    private Path mDrawPath;
    private Arc mOuterCircleArc, mInterCircleArc;

    @Override
    protected void initParams(Context context, Color color) {

        // 最大尺寸
        mOuterRF = getAllSize() * 1.0f;

        // 小圆尺寸
        mInterRF = mOuterRF * 0.7f;

        // 初始化画笔
        initPaint(mInterRF * 0.4f, color);

        // 旋转角度
        mRotateAngle = 0;
        // 圆范围
        mOuterCircleRectF = new RectFloat();
        mOuterCircleRectF.modify(NumCalcUtil.subtract(getViewCenterX(), mOuterRF), NumCalcUtil.subtract(getViewCenterY(), mOuterRF),
            NumCalcUtil.add(getViewCenterX(), mOuterRF), NumCalcUtil.add(getViewCenterY(), mOuterRF));
        mInterCircleRectF = new RectFloat();
        mInterCircleRectF.modify(NumCalcUtil.subtract(getViewCenterX(), mInterRF), NumCalcUtil.subtract(getViewCenterY(), mInterRF),
            NumCalcUtil.add(getViewCenterX(), mInterRF), NumCalcUtil.add(getViewCenterY(), mInterRF));
        mOuterCircleArc = new Arc();
        mInterCircleArc = new Arc();
        initPathMeasure();
        initPaths();
    }

    /**
     * 初始化画笔
     *
     * @param lineWidth 画笔线宽
     * @param color 画笔颜色
     */
    private void initPaint(float lineWidth, Color color) {
        mStrokePaint = new Paint();
        mStrokePaint.setStyle(Paint.Style.STROKE_STYLE);
        mStrokePaint.setStrokeWidth(lineWidth);
        mStrokePaint.setColor(color);
        mStrokePaint.setDither(true);
        mStrokePaint.setFilterBitmap(true);
        mStrokePaint.setStrokeCap(Paint.StrokeCap.ROUND_CAP);
        mStrokePaint.setStrokeJoin(Paint.Join.ROUND_JOIN);
    }

    private void initPathMeasure() {
        mDrawPath = new Path();
        mPathMeasure = new PathMeasure(mDrawPath, false);
    }

    private void initPaths() {
        // 中心折线
        mPath = new Path();
        float pointOffset = mOuterRF * 0.3f;
        float pointOffsetHalf = mOuterRF * 0.3f * 0.5f;
        mPath.moveTo(NumCalcUtil.subtract(getViewCenterX(), mOuterRF * 0.8f), getViewCenterY());
        mPath.lineTo(NumCalcUtil.subtract(getViewCenterX(), pointOffset), getViewCenterY());
        mPath.lineTo(NumCalcUtil.subtract(getViewCenterX(), pointOffsetHalf), NumCalcUtil.add(getViewCenterY(), pointOffsetHalf));
        mPath.lineTo(NumCalcUtil.add(getViewCenterX(), pointOffsetHalf), NumCalcUtil.subtract(getViewCenterY(), pointOffsetHalf));
        mPath.lineTo(NumCalcUtil.add(getViewCenterX(), pointOffset), getViewCenterY());
        mPath.lineTo(NumCalcUtil.add(getViewCenterX(), mOuterRF * 0.8f), getViewCenterY());
    }

    @Override
    protected void onDraw(Canvas canvas) {
        canvas.save();

        // 外圆
        mStrokePaint.setStrokeWidth(mOuterRF * 0.05f);
        mStrokePaint.setAlpha((int) (mAlpha * 0.6f));
        canvas.drawCircle(getViewCenterX(), getViewCenterY(), mOuterRF, mStrokePaint);
        canvas.drawCircle(getViewCenterX(), getViewCenterY(), mInterRF, mStrokePaint);
        canvas.restore();

        canvas.save();
        mStrokePaint.setStrokeWidth(mOuterRF * 0.1f);
        mStrokePaint.setAlpha(mAlpha);
        canvas.rotate(mRotateAngle, getViewCenterX(), getViewCenterY());
        mOuterCircleArc.setArc(0, 120, false);
        canvas.drawArc(mOuterCircleRectF, mOuterCircleArc, mStrokePaint);
        mOuterCircleArc.setArc(180, 120, false);
        canvas.drawArc(mOuterCircleRectF, mOuterCircleArc, mStrokePaint);
        canvas.restore();

        // 蛇
        canvas.save();
        mStrokePaint.setAlpha(mAlpha * 0.6f);
        canvas.drawPath(mDrawPath, mStrokePaint);
        canvas.restore();

        canvas.save();
        mStrokePaint.setStrokeWidth(mOuterRF * 0.1f);
        mStrokePaint.setAlpha(mAlpha);
        canvas.rotate(mAntiRotateAngle, getViewCenterX(), getViewCenterY());
        mInterCircleArc.setArc(60, 60, false);
        canvas.drawArc(mInterCircleRectF, mInterCircleArc, mStrokePaint);
        mInterCircleArc.setArc(180, 180, false);
        canvas.drawArc(mInterCircleRectF, mInterCircleArc, mStrokePaint);
        canvas.restore();
    }

    @Override
    protected void setAlpha(int alpha) {
        mAlpha = alpha;
    }

    @Override
    protected void prepareStart(AnimatorValue floatValueAnimator) {

    }

    @Override
    protected void prepareEnd() {

    }

    @Override
    protected void computeUpdateValue(AnimatorValue animation, float animatedValue) {
        mRotateAngle = 360 * animatedValue;
        mAntiRotateAngle = 360 * NumCalcUtil.subtract(1, animatedValue);
        switch (mCurrAnimatorState) {
            case 0:
                resetDrawPath();
                mPathMeasure.setPath(mPath, false);
                float stop = mPathMeasure.getLength() * animatedValue;
                float start = 0;
                mPathMeasure.getSegment(start, stop, mDrawPath, true);
                break;
            case 1:
                resetDrawPath();
                mPathMeasure.setPath(mPath, false);
                stop = mPathMeasure.getLength();
                start = mPathMeasure.getLength() * animatedValue;
                mPathMeasure.getSegment(start, stop, mDrawPath, true);
                break;
            default:
                break;
        }
    }

    @Override
    protected void setColorFilter(ColorFilter colorFilter) {
        mStrokePaint.setColorFilter(colorFilter);
    }

    private void resetDrawPath() {
        mDrawPath.reset();
        mDrawPath.lineTo(0, 0);
    }

    @Override
    public void onRepeat(Animator animator) {
        if (++mCurrAnimatorState > FINAL_STATE) {

            // 还原到第一阶段
            mCurrAnimatorState = 0;
        }
    }

}
